#include "task.h"

#ifdef TASK_DEBUG
#undef TASK_DEBUG
#define TASK_DEBUG 1
#include "log.h"
#endif

#ifndef TASK_MAX
#define TASK_MAX 4
#endif

typedef struct task_st
{
    uint32_t id;
    uint32_t state;
    pthread_t tid;
    work_impl work_func;
    void *work_arg;
    void *work_ret;
} task_t;

static struct
{
    task_t pool[TASK_MAX];
    pthread_once_t manager_once;
    task_t manager;
} task_global = {
    .pool = {},
    .manager_once = PTHREAD_ONCE_INIT,
    .manager = {0},
};

/// @brief 线程池管理者函数
/// @param arg NULL
/// @return
void *__manager_func(void *arg)
{
    // 休眠时间
    struct timespec sleep_time, remaining_time;
    // 1秒（1000000000纳秒）
    sleep_time.tv_sec = 1;
    sleep_time.tv_nsec = 0;

    task_t *task = NULL;
    // 管理线程工作->轮训所有已经TASK_FINISH的线程
    while (task_global.manager.state != TASK_MANAGER_EXIT)
    {
        for (size_t i = 0; i < TASK_MAX; i++)
        {
            task = &task_global.pool[i];
            if (task->state == TASK_FINISH) // 工作完成，回收线程
            {
                void *ret = NULL; // task_t * ret = NULL;
                pthread_join(task->tid, &ret);
#if TASK_DEBUG
                log_info("manager loop=>pool[%d] join ret:0x%x", task->id, task->work_ret);
#endif
                task->state = TASK_DIEOUT;
            }
        }
        // 使用nanosleep进行休眠
        // 如果nanosleep提前返回（因为被信号中断），remaining_time将包含未休眠的时间
        nanosleep(&sleep_time, &remaining_time);
        // if (remaining_time.tv_sec > 0 || remaining_time.tv_nsec > 0)
    }

#if TASK_DEBUG
    log_info("manager exit");
#endif

    // 要求管理线程退出，此时回收所有未被回收的线程
    for (size_t i = 0; i < TASK_MAX; i++)
    {
        task = &task_global.pool[i];
        if (task->state != TASK_DIEOUT)
        {
            void *ret = NULL; // task_t * ret = NULL;
            pthread_join(task->tid, &ret);
#if TASK_DEBUG
            log_info("manager exit=>pool[%d] join ret:0x%x", task->id, task->work_ret);
#endif
            task->state = TASK_DIEOUT;
        }
    }
}

/// @brief 释放管理者线程
void __manager_deinit()
{
    pthread_join(task_global.manager.tid, NULL);
}

/// @brief 初始化管理者线程
void __manager_init()
{
    task_global.manager = (task_t){
        .id = TASK_MAX,
        .state = TASK_WORK,
        .work_func = __manager_func,
        .work_arg = NULL,
        .work_ret = NULL,
    };
    int ret = pthread_create(&(task_global.manager.tid), NULL, task_global.manager.work_func, NULL);
    if (ret != 0)
    {
#if TASK_DEBUG
        log_info("manager thread init fail ret:%d", ret);
#endif
        task_global.manager.state = TASK_DIEOUT;
    }
    // 挂入钩子函数
    atexit(__manager_deinit);
}

void *__task_run(void *arg)
{
    task_t *task = (task_t *)arg;
    task->work_ret = task->work_func(task->work_arg);
    task->state = TASK_FINISH;
    pthread_exit(task);
}

uint32_t task_init(work_impl func, void *arg)
{
    // 使用task_ret(TASK_MAX) 获取state 查看管理线程启动状态
    pthread_once(&task_global.manager_once, __manager_init);
    for (size_t i = 0; i < TASK_MAX; i++)
    {
        if (task_global.pool[i].state == TASK_WORK)
        {
#if TASK_DEBUG
            log_info("pool[%d] working continue", i);
#endif
            continue;
        }
        else
        {
            task_global.pool[i] = (task_t){
                .id = i,
                .state = TASK_WORK,
                .work_func = func,
                .work_arg = arg,
                .work_ret = NULL,
            };
#if TASK_DEBUG
            log_info("pool[%d] work_func:0x%x work_arg:0x%x", i, task_global.pool[i].work_func, task_global.pool[i].work_arg);
#endif
            int ret = pthread_create(&(task_global.pool[i].tid), NULL, __task_run, &(task_global.pool[i]));
            if (ret != 0) // 系统不允许创建新任务
            {
#if TASK_DEBUG
                log_warning("sys fail ret:%d can't create new thread", ret);
#endif
                return TASK_MAX + 1;
            }
            return task_global.pool[i].id;
        }
    }
    // 线程池满，无法执行新任务
#if TASK_DEBUG
    log_warning("pool is full plz wait!");
#endif
    return TASK_MAX;
}

void *task_ret(uint32_t id, uint32_t *state)
{
    task_t *task = NULL;
    if (id < TASK_MAX) // 工作线程
    {
        task = &(task_global.pool[id]);
    }
    else if (id == TASK_MAX) // 管理线程
    {
        task = &(task_global.manager);
    }
    else // 越界
    {
        if (state != NULL)
            *state = UINT32_MAX;
        return NULL;
    }

    if (state != NULL)
        *state = task->state;
    return task->work_ret;
}

void task_exit()
{
#if TASK_DEBUG
    log_info("user call task exit");
#endif
    task_global.manager.state = TASK_MANAGER_EXIT;
}